import bpy
from . import Importer
import struct
import bmesh

def import_1s(self, context, filepath):
    Importer.read_1s(filepath)
    return {'FINISHED'}

def export_ktm(self, context, filepath):
    ff = open(filepath, 'wb')
    obj = bpy.context.selected_objects[0]
    vertices = obj.data.vertices
    uvs = []
    face_uvs = []
    normals = []
    links = []

    me = obj.data
    bpy.ops.object.mode_set(mode='EDIT')
    bm = bmesh.from_edit_mesh(me)
    for f in bm.faces:
        l = []
        for v in f.edges:
            try:
                if v.link_faces[0].index != f.index:
                    l.append(v.link_faces[0].index)
                else:
                    l.append(v.link_faces[1].index)
            except IndexError:
                l.append(65535)
        links.append(l)
    bpy.ops.object.mode_set(mode='OBJECT')

    me = obj.data
    bpy.ops.object.mode_set(mode='EDIT')
    bm = bmesh.from_edit_mesh(me)
    vlinks = []
    for vert in bm.verts:
        vl=[]
        for l in vert.link_edges:
           vl.append(l.other_vert(vert).index)
        vlinks.append(vl)
    bpy.ops.object.mode_set(mode='OBJECT')

    asdff = {}
    for i in range(len(links)):
        v = obj.data.polygons[i].vertices[0]
        link = vlinks[v]
        for l in link:
            asdff[str(l)] = v
        v = obj.data.polygons[i].vertices[1]
        link = vlinks[v]
        for l in link:
            asdff[str(l)] = v
        v = obj.data.polygons[i].vertices[2]
        link = vlinks[v]
        for l in link:
            asdff[str(l)] = v
    
    for face in obj.data.polygons:
        l = []
        for vert_idx, loop_idx in zip(face.vertices, face.loop_indices):
            uv = obj.data.uv_layers.active.data[loop_idx].uv
            uv_coords = [round(uv[0], 4), round(1-uv[1], 4)]
            try:
                if asdff[str(vert_idx)]:
                    uv_coords.append(asdff[str(vert_idx)])
            except KeyError:
                pass
            if uv_coords in uvs:
                l.append(uvs.index(uv_coords))
            else:
                uvs.append(uv_coords)
                l.append(len(uvs)-1)
        face_uvs.append(l)

    for face in obj.data.polygons:
        for i in range(3):
            normal_coords = vertices[face.vertices[i]].normal
            roundedd = [normal_coords[0], normal_coords[1], normal_coords[2]]
            if roundedd in normals:
                pass
            else:
                normals.append(roundedd)

    final = b''
    final += len(obj.data.vertices).to_bytes(4, 'little')
    for i in range(len(vertices)):
        final += struct.pack('f', vertices[i].co[0])
        final += struct.pack('f', vertices[i].co[1])
        final += struct.pack('f', vertices[i].co[2])
    final += len(normals).to_bytes(4, 'little')
    for i in range(len(normals)):
        final += struct.pack('f', normals[i][0])
        final += struct.pack('f', normals[i][1])
        final += struct.pack('f', normals[i][2])
    # final += b'\x00\x00\x00\x00'
    final += len(uvs).to_bytes(4, 'little')
    for i in range(len(uvs)):
        if len(uvs[i]) == 3:
            final += uvs[i][2].to_bytes(2, 'little')
        else:
            final += i.to_bytes(2, 'little')
        final += i.to_bytes(2, 'little')
        final += struct.pack('f', round(uvs[i][0], 4))
        final += struct.pack('f', round(uvs[i][1], 4))


    final += (len(obj.data.polygons)).to_bytes(4, 'little')
    for i in range(len(obj.data.polygons)):
        final += (face_uvs[i][0]).to_bytes(2, 'little')
        final += (face_uvs[i][1]).to_bytes(2, 'little')
        final += (face_uvs[i][2]).to_bytes(2, 'little')

        final += (links[i][0]).to_bytes(2, 'little')
        final += (links[i][1]).to_bytes(2, 'little')
        final += (links[i][2]).to_bytes(2, 'little')
        
        final += (obj.data.polygons[i].vertices[0]).to_bytes(2, 'little')
        final += (obj.data.polygons[i].vertices[1]).to_bytes(2, 'little')
        final += (obj.data.polygons[i].vertices[2]).to_bytes(2, 'little')

        if 65535 in links[i]:
            final += b'\x00\x01'
        else:
            final += b'\x00\x00'

    ff.write(final)
    ff.close()

    return {'FINISHED'}


# ImportHelper is a helper class, defines filename and
# invoke() function which calls the file selector.
from bpy_extras.io_utils import ImportHelper
from bpy.props import StringProperty
from bpy.types import Operator


class Import1s(Operator, ImportHelper):
    bl_idname = "import_1s.import"  # important since its how bpy.ops.import_test.some_data is constructed
    bl_label = "Import 1s"

    # ImportHelper mixin class uses this
    filename_ext = ".1s"

    filter_glob: StringProperty(
        default="*.1s",
        options={'HIDDEN'},
        maxlen=255,  # Max internal buffer length, longer would be clamped.
    )

    def execute(self, context):
        return import_1s(self, context, self.filepath)
    
class ExportKTM(Operator, ImportHelper):
    """Kartrider Model Export"""
    bl_idname = "export_ktm.import"  # important since its how bpy.ops.import_test.some_data is constructed
    bl_label = "Export ktm"

    # ImportHelper mixin class uses this
    filename_ext = ".ktm"

    filter_glob: StringProperty(
        default="*.ktm",
        options={'HIDDEN'},
        maxlen=255,  # Max internal buffer length, longer would be clamped.
    )

    def execute(self, context):
        return export_ktm(self, context, self.filepath)